package top.byteio.common.core.crypto;

import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;

/**
 * 散列算法（消息摘要算法、签名算法）是单向不可逆的，无法通过加密后的散列值反推原始值，
 * 相同的内容用同样的摘要算法获得的散列值是一样的，所以常用于验证数据的完整性。
 * 该算法主要分为三大类：MD（Message Digest，消息摘要算法）、SHA（Secure HashAlgorithm，安全散列算法）
 * 和MAC（Message Authentication Code，消息认证码算法）。MD系列算法包括MD2、MD4和MD5共3种算法；
 * SHA算法主要包括其代表算法SHA-1和SHA-1算法的变种SHA-2系列算法（包含SHA-224、SHA-256、SHA-384和SHA-512）；
 * MAC算法综合了上述两种算法，主要包括HmacMD5、HmacSHA1、HmacSHA256、HmacSHA384和HmacSHA512算法。这
 * 消息摘要算法的结果我们一般将其转换为16进制字符串，方便阅读传输。
 * <p>SHA算法是基于MD4算法实现的，作为MD算法的继任者，成为了新一代的消息摘要算法的代表。
 * SHA与MD算法不同之处主要在于摘要长度，SHA算法的摘要更长，安全性更高。
 * SHA算法家族目前共有SHA-1、SHA-224、SHA-256、SHA-384和SHA-512五种算法，通常将后四种算法并称为SHA-2算法。
 * Java支持SHA-1、SHA-256、SHA-384、SHA-224和SHA-512五种算法，其中SHA的写法等价于SHA-1。
 * SHA系列算法的实现也是通过MessageDigest类来完成的.</p>
 *
 * @author lerry
 * @since 2023/6/22 19:20
 */
@Slf4j
public class SHA1 implements ICrypt {

    /**
     * sha1加密
     *
     * @param input 待加密数据
     * @return java.lang.String
     * @author lerry
     * @since 2023/6/22 19:55
     */
    public static String encode(String input) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
            byte[] inputBytes = input.getBytes(StandardCharsets.UTF_8); // 明确编码
            byte[] hashBytes = messageDigest.digest(inputBytes);
            StringBuilder hashBuilder = new StringBuilder(40); // 指定初始容量
            for (byte b : hashBytes) {
                hashBuilder.append(String.format("%02x", b));
            }
            return hashBuilder.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Error hashing input.", e);
        }
    }

    /**
     * 校验input被加密和encoded是否一样
     *
     * @param input   未加密数据
     * @param encoded 加密数据
     * @return boolean
     * @author lerry
     * @since 2023/6/22 19:57
     */
    public static boolean verify(String input, String encoded) {
        return Objects.equals(encode(input), encoded);
    }
}
